<template>
  <a-dropdown
    v-model:open="visible"
    class="avic-tree-select"
    :disabled="disabled"
    :trigger="['click']"
    :overlay-style="
      Object.assign(
        {
          background: '#fff',
          height: treeSelectHeight + 'px',
          width: showContainer === 'form' ? '100%' : treeSelectWidth + 'px',
          boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)'
        },
        dropdownStyle
      )
    "
    :get-popup-container="showContainer === 'form' ? (e) => e.parentElement : null"
  >
    <a-input v-model:value="showValue" @change="handleInput" @click="handleTrigger">
      <template #suffix>
        <!-- <AvicIcon svg="avic-app-channel" @click="handleTrigger" /> -->
        <avic-icon svg="avic-component-tree" color="#86909c" @click="handleTrigger" />
      </template>
    </a-input>
    <template #overlay>
      <div v-on:mouseleave="visible = false">
        <a-input-search
          class="avic-tree-input-search"
          style="padding: 4px"
          :allow-clear="true"
          :placeholder="placeholder"
          @search="handleSearchTree"
        />
        <a-spin :spinning="loading">
          <div :style="{ height: treeSelectHeight - 50 + 'px', overflow: 'auto', padding: '4px' }">
            <a-tree
              v-if="treeData && treeData.length > 0"
              v-model:expanded-keys="expandedKeys"
              v-model:selectedKeys="selectedKeys"
              :tree-data="treeData"
              :load-data="onLoadData"
              :show-line="false"
              :default-expand-all="true"
              :multiple="multiple"
              show-icon
              @expand="onExpand"
              @select="selectNode"
            >
              <template #title="{ dataRef }">
                <span v-if="dataRef.title.indexOf(searchValue) > -1" :title="dataRef.title">
                  {{ dataRef.title.substr(0, dataRef.title.indexOf(searchValue)) }}
                  <span style="color: #f50">{{ searchValue }}</span>
                  {{ dataRef.title.substr(dataRef.title.indexOf(searchValue) + searchValue.length) }}
                </span>
                <span v-else :title="dataRef.title">{{ dataRef.title }}</span>
              </template>
              <template #icon="{ expanded, dataRef }">
                <template v-if="isOnlyFolder">
                  <avic-icon v-if="!expanded" svg="avic-folder-3-fill" color="#ffb800" />
                  <avic-icon v-if="expanded" svg="avic-folder-open-fill" color="#ffb800" />
                </template>
                <template v-else>
                  <avic-icon v-if="dataRef.isLeaf" svg="avic-file-fill" color="#3370ff" />
                  <avic-icon v-if="!expanded && !dataRef.isLeaf" svg="avic-folder-3-fill" color="#ffb800" />
                  <avic-icon v-if="expanded && !dataRef.isLeaf" svg="avic-folder-open-fill" color="#ffb800" />
                </template>
              </template>
            </a-tree>
            <template v-else>
              <a-empty :image="simpleImage" />
            </template>
          </div>
        </a-spin>
      </div>
    </template>
  </a-dropdown>
</template>
<script lang="ts" setup>
import { getTreeData, searchTree } from '@/api/avic/system/AvicTreeSelectApi';
import { getExpandedKeys, getAllExpandedKeys, setNodeSlots } from '@/utils/tree-util';
import { Empty, Form } from 'ant-design-vue';

const { proxy } = getCurrentInstance();
const props = defineProps({
  value: { type: String, default: '' },
  /** 树的后台服务地址 */
  baseUrl: { type: String, default: '' },
  /** 树请求的后台服务地址 */
  loadTreeUrl: { type: String, default: '' },
  /** 树搜索的后台服务地址 */
  searchTreeUrl: { type: String, default: '' },
  /** 树选择时默认传入的父节点id，用户默认选中id  */
  parentId: { type: String, default: '' },
  /** 树选择时默认传入的父节点title，用户默认选中展示  */
  parentTitle: { type: String, default: '' },
  /** 是否禁用控件 */
  disabled: { type: Boolean, default: false },
  /** 是否允许多选 */
  multiple: { type: Boolean, default: false },
  /** 选择页高度 */
  treeSelectHeight: { type: Number, default: 260 },
  /** 允许选择非叶子节点,默认允许 */
  allowSelectNonIsLeaf: { type: Boolean, default: true },
  /** 下拉弹出框样式 */
  dropdownStyle: { type: Object, required: false, default: () => null },
  /** 搜索框提示信息 */
  placeholder: { type: String, default: '输入回车查询' },
  /** 所处容器默认form表单,table表示行编辑时使用 */
  showContainer: { type: String, default: 'form' },
  /** 选择页宽度，仅在showContainer为table时适用 */
  treeSelectWidth: { type: Number, default: 200 },
  /** 默认根节点id */
  rootParentId: { type: String, default: '-1' },
  /** 是否允许选择根节点 */
  allowSelectRoot: { type: Boolean, default: true },
  /** 是否允许清空 */
  allowClear: { type: Boolean, default: true },
  /** 禁用父节点 */
  mainDisabled: { type: Boolean, default: true },
  /** 只返回文件夹 */
  isOnlyFolder: { type: Boolean, default: false }
});
// 数据双向绑定事件
const $emit = defineEmits(['input', 'change', 'select', 'update:value', 'callback', 'changeName']);
const formItemContext = Form.useInjectFormItemContext();
const state = reactive({
  bindValue: props.parentId,
  showValue: props.parentTitle,
  valueList: [props.parentId], // 多选时使用
  showValueList: [],
  visible: false,
  loading: false,
  defaultRootParentId: '-1',
  treeData: [],
  expandedKeys: [],
  selectedKeys: [],
  searchValue: '',
  simpleImage: Empty.PRESENTED_IMAGE_SIMPLE
});
const {
  bindValue,
  showValue,
  valueList,
  showValueList,
  visible,
  loading,
  defaultRootParentId,
  treeData,
  expandedKeys,
  selectedKeys,
  searchValue,
  simpleImage
} = toRefs(state);

watch(
  bindValue,
  (newVal) => {
    $emit('input', newVal);
    $emit('change', newVal);
    $emit('update:value', newVal);
    $emit('changeName', showValue.value);
    formItemContext?.onFieldChange && formItemContext.onFieldChange();
  },
  { immediate: true }
);
watch(
  () => props.value,
  (newVal) => {
    // $emit('input', newVal);
    // $emit('change', newVal);
    // $emit('update:value', newVal);
    if (!newVal) {
      showValue.value = '';
      showValueList.value = [];
    }
  },
  { immediate: true }
);
watch(
  () => props.value,
  (newVal) => {
    if (newVal) {
      bindValue.value = newVal;
    }
    if (!newVal) {
      showValue.value = '';
      showValueList.value = [];
    }
  },
  { immediate: true }
);
watch(
  () => props.parentTitle,
  (newVal) => {
    if (newVal) {
      showValue.value = newVal;
      showValueList.value.push(newVal);
    }
  },
  { immediate: true }
);
// 当中默认处理
watch(
  () => props.parentId,
  (newVal) => {
    if (newVal) {
      bindValue.value = newVal;
      $emit('input', newVal);
      $emit('change', newVal);
      $emit('update:value', newVal);
    }
  },
  { immediate: true }
);
function initData(pid, ptitle) {
  showValue.value = ptitle;
  showValueList.value.push(ptitle);
  bindValue.value = pid;
  valueList.value = [pid]; // 多选时使用
}
function getTreeList() {
  loading.value = true;
  const expandLevel = 2;
  treeData.value = [];
  expandedKeys.value = [];
  getTreeData(props.loadTreeUrl || props.baseUrl, expandLevel, defaultRootParentId.value, !!props.baseUrl)
    .then((response) => {
      setNodeSlots(response.data);
      getExpandedKeys(response.data, expandLevel, expandedKeys.value);
      treeData.value = response.data;
      selectedKeys.value = [props.parentId];
      loading.value = false;
    })
    .catch(() => {
      loading.value = false;
    });
}
function reloadTreeData() {
  treeData.value = [];
}
/**
 * 树节点查询
 * @param {Object} value
 * @param {Object} e
 */
function handleSearchTree(value) {
  if (value.trim().length === 0) {
    getTreeList();
  } else {
    const searchText = { searchText: value };
    loading.value = true;
    treeData.value = [];
    expandedKeys.value = [];
    searchTree(props.searchTreeUrl || props.baseUrl, searchText, !!props.baseUrl).then((response) => {
      setNodeSlots(response.data);
      getAllExpandedKeys(response.data, expandedKeys.value);
      treeData.value = response.data;
      loading.value = false;
    });
  }
  /* Object.assign(this, {
    expandedKeys: this.expandedKeys,
    searchValue: value
  }) */
  searchValue.value = value;
}
/**
 * 异步加载树节点
 * @param {Object} treeNode
 */
function onLoadData(treeNode) {
  return new Promise<void>((resolve) => {
    if (treeNode.dataRef.children) {
      resolve();
      return;
    }
    getTreeData(props.loadTreeUrl || props.baseUrl, 1, treeNode.dataRef.id, !!props.baseUrl).then((response) => {
      setNodeSlots(response.data);
      treeNode.dataRef.children = response.data;
      treeData.value = [...treeData.value];
      resolve();
    });
  });
}
function onExpand(_expandedKeys) {
  expandedKeys.value = _expandedKeys;
}
function handleInput(e) {
  // 允许清空且点击清空图标时清空数据
  if (!showValue.value && e.type === 'click') {
    // 清空输入框时，清空树选中
    selectedKeys.value = [];
    valueList.value = [];
    showValueList.value = [];
    bindValue.value = '';
    $emit('select', [], null, e);
    if (!props.allowClear) {
      // 清楚时不需要重新加载数据
      getTreeList();
    }
  } else {
    showValue.value = props.parentTitle;
  }
}
function handleTrigger(e) {
  if (treeData.value.length === 0) {
    getTreeList();
  }
  e.stopPropagation();
  if (!props.disabled) {
    visible.value = !visible.value;
  }
}
/**
 * 树选中事件
 */
function selectNode(_selectedKeys, { selectedNodes, node, event }) {
  if (!props.allowSelectNonIsLeaf && node.dataRef.isLeaf === false) {
    // 禁止选择非叶子节点，并且当前节点为非叶子节点
    proxy.$message.warning('禁止选择非叶子节点！');
    return;
  }
  if (props.allowSelectRoot && node.dataRef.parentId === props.rootParentId) {
    proxy.$message.warning('禁止选择根节点节点！');
    return;
  }
  if (props.mainDisabled && node?.attributes?.moduleType === '1') {
    proxy.$message.warning('禁止选择主模块节点！');
    return;
  }
  if (!props.multiple) {
    visible.value = false;
    (bindValue.value = node.dataRef.id), (showValue.value = node.dataRef.title);
    selectedKeys.value = _selectedKeys;
    $emit('update:value', bindValue.value);
    // 触发表单字段的change校验
    formItemContext?.onFieldChange && formItemContext.onFieldChange();
    $emit('callback', node);
    $emit('select', bindValue.value, node, event);
  } else {
    // 选择前节点选中状态
    const { selected } = node;
    if (selected) {
      valueList.value = valueList.value.filter((id) => id !== node.dataRef.id);
      showValueList.value = showValueList.value.filter((title) => title !== node.dataRef.title);
    } else {
      valueList.value.push(node.dataRef.id);
      showValueList.value.push(node.dataRef.title);
    }
    bindValue.value = valueList.value.toString();
    showValue.value = showValueList.value.toString();
    selectedKeys.value = _selectedKeys;
    $emit('update:value', bindValue.value);
    // 触发表单字段的change校验
    formItemContext?.onFieldChange && formItemContext.onFieldChange();
    $emit('callback', selectedNodes);
    $emit('select', bindValue.value, selectedNodes, event);
  }
}
defineExpose({
  reloadTreeData,
  initData
});
</script>
